|
1
|
|
|
"use strict"; |
|
2
|
|
|
|
|
3
|
|
|
const fs = require ('fs') |
|
4
|
|
|
const log = require ('ololog') |
|
5
|
|
|
const ansi = require ('ansicolor').nice |
|
|
|
|
|
|
6
|
|
|
|
|
7
|
|
|
//----------------------------------------------------------------------------- |
|
8
|
|
|
|
|
9
|
|
|
function regexAll (text, array) { |
|
10
|
|
|
for (let i in array) { |
|
11
|
|
|
let regex = array[i][0] |
|
12
|
|
|
regex = typeof regex == 'string' ? new RegExp (regex, 'g') : new RegExp (regex) |
|
13
|
|
|
text = text.replace (regex, array[i][1]) |
|
14
|
|
|
} |
|
15
|
|
|
return text |
|
16
|
|
|
} |
|
17
|
|
|
|
|
18
|
|
|
//----------------------------------------------------------------------------- |
|
19
|
|
|
|
|
20
|
|
|
let ccxtjs = fs.readFileSync ('ccxt.js', 'utf8') |
|
21
|
|
|
let contents = ccxtjs.match (/\/\/====(?:[\s\S]+?)\/\/====/) [0] |
|
22
|
|
|
let exchanges |
|
23
|
|
|
let regex = /^var ([\S]+) =\s*(?:extend\s*\(([^\,]+)\,\s*)?{([\s\S]+?)^}/gm // exchange class |
|
24
|
|
|
|
|
25
|
|
|
let python = [] |
|
26
|
|
|
let pythonAsync = [] |
|
27
|
|
|
let php = [] |
|
28
|
|
|
|
|
29
|
|
|
//----------------------------------------------------------------------------- |
|
30
|
|
|
|
|
31
|
|
|
while (exchanges = regex.exec (contents)) { |
|
32
|
|
|
|
|
33
|
|
|
let id = exchanges[1] |
|
34
|
|
|
|
|
35
|
|
|
let parent = exchanges[2] |
|
36
|
|
|
|
|
37
|
|
|
let all = exchanges[3].trim ().split (/\,\s*\n\s*\n/) |
|
38
|
|
|
let params = ' ' + all[0] |
|
39
|
|
|
let methods = all.slice (1) |
|
40
|
|
|
|
|
41
|
|
|
let py = [] |
|
42
|
|
|
let pyAsync = [] |
|
43
|
|
|
let ph = [] |
|
44
|
|
|
|
|
45
|
|
|
params = params.split ("\n") |
|
46
|
|
|
|
|
47
|
|
|
let pyParams = params |
|
48
|
|
|
.join ("\n ") |
|
49
|
|
|
.replace (/ true/g, ' True') |
|
50
|
|
|
.replace (/ false/g, ' False') |
|
51
|
|
|
.replace (/ undefined/g, ' None') |
|
52
|
|
|
.replace (/ \/\//g, ' #') |
|
53
|
|
|
.replace (/\{ /g, '{') // PEP8 E201 |
|
54
|
|
|
.replace (/\[ /g, '[') // PEP8 E201 |
|
55
|
|
|
.replace (/([^\s]+) \]/g, '$1]') // PEP8 E202 |
|
56
|
|
|
.replace (/([^\s]+) \}\,/g, '$1},') // PEP8 E202 |
|
57
|
|
|
|
|
58
|
|
|
function pyAddClass (py) { |
|
|
|
|
|
|
59
|
|
|
py.push ('') |
|
60
|
|
|
py.push ('class ' + id + ' (' + (parent ? parent : 'Exchange') + '):') |
|
61
|
|
|
py.push ('') |
|
62
|
|
|
py.push (' def __init__(self, config={}):') |
|
63
|
|
|
py.push (' params = {') |
|
64
|
|
|
py.push (' ' + pyParams + ((all.length > 1) ? ',' : '')) |
|
65
|
|
|
py.push (' }') |
|
66
|
|
|
py.push (' params.update(config)') |
|
67
|
|
|
py.push (' super(' + id + ', self).__init__(params)') |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
pyAddClass (py); |
|
71
|
|
|
pyAddClass (pyAsync); |
|
72
|
|
|
|
|
73
|
|
|
let phParams = params |
|
74
|
|
|
.join ("\n ") |
|
75
|
|
|
.replace (/ undefined/g, ' null') |
|
76
|
|
|
.replace (/': /g, "' => ") |
|
77
|
|
|
.replace (/ {/g, ' array (') |
|
78
|
|
|
.replace (/ \[/g, ' array (') |
|
79
|
|
|
.replace (/\}([\,\n]|$)/g, ')$1') |
|
80
|
|
|
.replace (/\]/g, ')') |
|
81
|
|
|
|
|
82
|
|
|
ph.push ('') |
|
83
|
|
|
ph.push ('class ' + id + ' extends ' + (parent ? parent : 'Exchange') + ' {') |
|
84
|
|
|
ph.push ('') |
|
85
|
|
|
ph.push (' public function __construct ($options = array ()) {') |
|
86
|
|
|
ph.push (' parent::__construct (array_merge(array (') |
|
87
|
|
|
ph.push (' ' + phParams + ((all.length > 1) ? ',' : '')) |
|
88
|
|
|
ph.push (' ), $options));') |
|
89
|
|
|
ph.push (' }') |
|
90
|
|
|
|
|
91
|
|
|
for (let i = 0; i < methods.length; i++) { |
|
92
|
|
|
let part = methods[i].trim () |
|
93
|
|
|
let lines = part.split ("\n") |
|
94
|
|
|
let header = lines[0].trim () |
|
95
|
|
|
let regex2 = /(async |)([\S]+)\s\(([^)]*)\)\s*{/g // exchange method |
|
96
|
|
|
let matches = regex2.exec (header) |
|
97
|
|
|
let keyword = matches[1] |
|
98
|
|
|
let method = matches[2] |
|
99
|
|
|
let args = matches[3].trim () |
|
100
|
|
|
|
|
101
|
|
|
method = method.replace ('fetchBalance', 'fetch_balance') |
|
102
|
|
|
// .replace ('fetchCategories', 'fetch_categories') |
|
103
|
|
|
.replace ('loadMarkets', 'load_markets') |
|
104
|
|
|
.replace ('fetchMarkets', 'fetch_markets') |
|
105
|
|
|
.replace ('fetchOrderBook', 'fetch_order_book') |
|
106
|
|
|
.replace ('fetchOHLCV', 'fetch_ohlcv') |
|
107
|
|
|
.replace ('parseOHLCVs', 'parse_ohlcvs') |
|
108
|
|
|
.replace ('parseOHLCV', 'parse_ohlcv') |
|
109
|
|
|
.replace ('fetchTickers', 'fetch_tickers') |
|
110
|
|
|
.replace ('fetchTicker', 'fetch_ticker') |
|
111
|
|
|
.replace ('parseTicker', 'parse_ticker') |
|
112
|
|
|
.replace ('parseTradesData', 'parse_trades_data') |
|
113
|
|
|
.replace ('parseTrades', 'parse_trades') |
|
114
|
|
|
.replace ('parseTrade', 'parse_trade') |
|
115
|
|
|
.replace ('parseOrderBook', 'parse_order_book') |
|
116
|
|
|
.replace ('parseBidAsks', 'parse_bidasks') |
|
117
|
|
|
.replace ('parseBidAsk', 'parse_bidask') |
|
118
|
|
|
.replace ('parseOrders', 'parse_orders') |
|
119
|
|
|
.replace ('parseOrder', 'parse_order') |
|
120
|
|
|
.replace ('fetchTrades', 'fetch_trades') |
|
121
|
|
|
.replace ('fetchOrderStatus', 'fetch_order_status') |
|
122
|
|
|
.replace ('fetchOrderTrades', 'fetch_order_trades') |
|
123
|
|
|
.replace ('fetchOrders', 'fetch_orders') |
|
124
|
|
|
.replace ('fetchOrder', 'fetch_order') |
|
125
|
|
|
.replace ('fetchOpenOrders', 'fetch_open_orders') |
|
126
|
|
|
.replace ('fetchMyTrades', 'fetch_my_trades') |
|
127
|
|
|
.replace ('fetchAllMyTrades', 'fetch_all_my_trades') |
|
128
|
|
|
.replace ('createOrder', 'create_order') |
|
129
|
|
|
.replace ('cancelOrder', 'cancel_order') |
|
130
|
|
|
.replace ('signIn', 'sign_in') |
|
131
|
|
|
|
|
132
|
|
|
args = args.length ? args.split (',').map (x => x.trim ()) : [] |
|
133
|
|
|
|
|
134
|
|
|
let phArgs = args.join (', $').trim () |
|
135
|
|
|
phArgs = phArgs.length ? ('$' + phArgs) : '' |
|
136
|
|
|
|
|
137
|
|
|
let pyArgs = args.map (x => x.replace (' = ', '=')).join (', ') |
|
138
|
|
|
|
|
139
|
|
|
let variables = args.map (arg => arg.split ('=').map (x => x.trim ()) [0]) |
|
140
|
|
|
|
|
141
|
|
|
let body = lines.slice (1, -1).join ("\n") |
|
142
|
|
|
|
|
143
|
|
|
let regex3 = /[^a-zA-Z0-9_]let\s+(?:\[([^\]]+)\]|([a-zA-Z0-9_]+))/g // local variables |
|
144
|
|
|
|
|
145
|
|
|
let localVariablesMatches |
|
146
|
|
|
while (localVariablesMatches = regex3.exec (body)) { |
|
147
|
|
|
let m = localVariablesMatches[1] ? localVariablesMatches[1] : localVariablesMatches[2] |
|
148
|
|
|
m = m.trim ().split (', ') |
|
149
|
|
|
m.forEach (x => variables.push (x.trim ())) |
|
150
|
|
|
variables.push (localVariablesMatches[1]) |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
let phVarsRegex = variables.map (x => [ "([^$$a-zA-Z0-9\\.\\>'_])" + x + "([^a-zA-Z0-9'_])", '$1$$' + x + '$2' ]) |
|
154
|
|
|
|
|
155
|
|
|
let pyRegex = [ |
|
156
|
|
|
[ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] is None' ], |
|
157
|
|
|
[ /undefined/g, 'None' ], |
|
158
|
|
|
[ /this\.stringToBinary\s*\((.*)\)/g, '$1' ], |
|
159
|
|
|
[ /this\.stringToBase64\s/g, 'base64.b64encode' ], |
|
160
|
|
|
[ /this\.base64ToBinary\s/g, 'base64.b64decode' ], |
|
161
|
|
|
[ /\.safeFloat\s/g, '.safe_float'], |
|
162
|
|
|
[ /\.binaryConcat\s/g, '.binary_concat'], |
|
163
|
|
|
[ /\.binaryToString\s/g, '.binary_to_string' ], |
|
164
|
|
|
[ /\.implodeParams\s/g, '.implode_params'], |
|
165
|
|
|
[ /\.extractParams\s/g, '.extract_params'], |
|
166
|
|
|
[ /\.parseOHLCVs/g, '.parse_ohlcvs'], |
|
167
|
|
|
[ /\.parseOHLCV/g, '.parse_ohlcv'], |
|
168
|
|
|
[ /\.parseTicker\s/g, '.parse_ticker'], |
|
169
|
|
|
[ /\.parseTradesData\s/g, '.parse_trades_data'], |
|
170
|
|
|
[ /\.parseTrades\s/g, '.parse_trades'], |
|
171
|
|
|
[ /\.parseTrade\s/g, '.parse_trade'], |
|
172
|
|
|
[ /\.parseOrderBook\s/g, '.parse_order_book'], |
|
173
|
|
|
[ /\.parseBidAsks\s/g, '.parse_bidasks'], |
|
174
|
|
|
[ /\.parseBidAsk\s/g, '.parse_bidask'], |
|
175
|
|
|
[ /\.parseOrders\s/g, '.parse_orders'], |
|
176
|
|
|
[ /\.parseOrder\s/g, '.parse_order'], |
|
177
|
|
|
[ /\.indexBy\s/g, '.index_by'], |
|
178
|
|
|
[ /\.sortBy\s/g, '.sort_by'], |
|
179
|
|
|
[ /\.marketIds\s/g, '.market_ids'], |
|
180
|
|
|
[ /\.marketId\s/g, '.market_id'], |
|
181
|
|
|
[ /\.fetchOrderStatus\s/g, '.fetch_order_status'], |
|
182
|
|
|
[ /\.fetchOpenOrders\s/g, '.fetch_open_orders'], |
|
183
|
|
|
[ /\.fetchOrders\s/g, '.fetch_orders'], |
|
184
|
|
|
[ /\.loadMarkets\s/g, '.load_markets'], |
|
185
|
|
|
[ /\.encodeURIComponent\s/g, '.encode_uri_component'], |
|
186
|
|
|
// [ /this\.urlencode\s/g, '_urlencode.urlencode ' ], // use self.urlencode instead |
|
187
|
|
|
[ /this\./g, 'self.' ], |
|
188
|
|
|
[ /([^a-zA-Z\'])this([^a-zA-Z])/g, '$1self$2' ], |
|
189
|
|
|
[ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1$2' ], |
|
190
|
|
|
[ /([^a-zA-Z0-9_])let\s/g, '$1' ], |
|
191
|
|
|
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ], |
|
192
|
|
|
[ /Object\.keys\s*\((.*)\)/g, 'list($1.keys())' ], |
|
193
|
|
|
[ /\[([^\]]+)\]\.join\s*\(([^\)]+)\)/g, "$2.join([$1])" ], |
|
194
|
|
|
[ /hash \(([^,]+)\, \'(sha[0-9])\'/g, "hash($1, '$2'" ], |
|
195
|
|
|
[ /hmac \(([^,]+)\, ([^,]+)\, \'(md5)\'/g, 'hmac($1, $2, hashlib.$3' ], |
|
196
|
|
|
[ /hmac \(([^,]+)\, ([^,]+)\, \'(sha[0-9]+)\'/g, 'hmac($1, $2, hashlib.$3' ], |
|
197
|
|
|
[ /throw new ([\S]+) \((.*)\)/g, 'raise $1($2)'], |
|
198
|
|
|
[ /throw ([\S]+)/g, 'raise $1'], |
|
199
|
|
|
[ /try {/g, 'try:'], |
|
200
|
|
|
[ /\}\s+catch \(([\S]+)\) {/g, 'except Exception as $1:'], |
|
201
|
|
|
[ /([\s\(])extend(\s)/g, '$1self.extend$2' ], |
|
202
|
|
|
[ /\} else if/g, 'elif' ], |
|
203
|
|
|
[ /if\s+\((.*)\)\s+\{/g, 'if $1:' ], |
|
204
|
|
|
[ /if\s+\((.*)\)\s*[\n]/g, "if $1:\n" ], |
|
205
|
|
|
[ /\}\s*else\s*\{/g, 'else:' ], |
|
206
|
|
|
[ /else\s*[\n]/g, "else:\n" ], |
|
207
|
|
|
[ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(?:\<=|\>=|<|>)\s*(.*)\.length\s*\;[^\)]+\)\s*{/g, 'for $1 in range($2, len($3)):'], |
|
208
|
|
|
[ /\s\|\|\s/g, ' or ' ], |
|
209
|
|
|
[ /\s\&\&\s/g, ' and ' ], |
|
210
|
|
|
[ /\!([^\=])/g, 'not $1'], |
|
211
|
|
|
[ /([^\s]+)\.length/g, 'len($1)' ], |
|
212
|
|
|
[ /\.push\s*\(([\s\S]+?)\);/g, '.append($1);' ], |
|
213
|
|
|
[ /^\s*}\s*[\n]/gm, '' ], |
|
214
|
|
|
[ /;/g, '' ], |
|
215
|
|
|
[ /\.toUpperCase\s*/g, '.upper' ], |
|
216
|
|
|
[ /\.toLowerCase\s*/g, '.lower' ], |
|
217
|
|
|
[ /JSON\.stringify\s*/g, 'json.dumps' ], |
|
218
|
|
|
// [ /\'%([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "'{:$1}'.format($2)" ], |
|
219
|
|
|
[ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "'{:.$2f}'.format($1)" ], |
|
220
|
|
|
[ /parseFloat\s*/g, 'float'], |
|
221
|
|
|
[ /parseInt\s*/g, 'int'], |
|
222
|
|
|
[ /self\[([^\]+]+)\]/g, 'getattr(self, $1)' ], |
|
223
|
|
|
[ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], |
|
224
|
|
|
[ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], |
|
225
|
|
|
[ /Math\.floor\s*\(([^\)]+)\)/g, 'int(math.floor($1))' ], |
|
226
|
|
|
[ /Math\.abs\s*\(([^\)]+)\)/g, 'abs($1)' ], |
|
227
|
|
|
[ /Math\.round\s*\(([^\)]+)\)/g, 'int(round($1))' ], |
|
228
|
|
|
[ /(\([^\)]+\)|[^\s]+)\s*\?\s*(\([^\)]+\)|[^\s]+)\s*\:\s*(\([^\)]+\)|[^\s]+)/g, '$2 if $1 else $3'], |
|
229
|
|
|
[/ \/\//g, ' #' ], |
|
230
|
|
|
[ /\.indexOf/g, '.find'], |
|
231
|
|
|
[ /\strue/g, ' True'], |
|
232
|
|
|
[ /\sfalse/g, ' False'], |
|
233
|
|
|
[ /\(([^\s]+)\sin\s([^\)]+)\)/g, '($1 in list($2.keys()))' ], |
|
234
|
|
|
[ /([^\s]+\s*\(\))\.toString\s+\(\)/g, 'str($1)' ], |
|
235
|
|
|
[ /([^\s]+)\.toString \(\)/g, 'str($1)' ], |
|
236
|
|
|
[ /([^\s]+)\.join\s*\(\s*([^\)\[\]]+?)\s*\)/g, '$2.join($1)' ], |
|
237
|
|
|
[ /Math\.(max|min)\s/g, '$1' ], |
|
238
|
|
|
[ /console\.log\s/g, 'print'], |
|
239
|
|
|
[ /process\.exit\s+/g, 'sys.exit'], |
|
240
|
|
|
[ /([^+=\s]+) \(/g, '$1(' ], // PEP8 E225 remove whitespaces before left ( round bracket |
|
241
|
|
|
[ /\[ /g, '[' ], // PEP8 E201 remove whitespaces after left [ square bracket |
|
242
|
|
|
[ /\{ /g, '{' ], // PEP8 E201 remove whitespaces after left { bracket |
|
243
|
|
|
[ /([^\s]+) \]/g, '$1]' ], // PEP8 E202 remove whitespaces before right ] square bracket |
|
244
|
|
|
[ /([^\s]+) \}/g, '$1}' ], // PEP8 E202 remove whitespaces before right } bracket |
|
245
|
|
|
] |
|
246
|
|
|
|
|
247
|
|
|
let phRegex = [ |
|
248
|
|
|
[ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] == null' ], |
|
249
|
|
|
[ /undefined/g, 'null' ], |
|
250
|
|
|
[ /this\.extend/g, 'array_merge' ], |
|
251
|
|
|
[ /this\.stringToBinary\s*\((.*)\)/g, '$1' ], |
|
252
|
|
|
[ /this\.stringToBase64/g, 'base64_encode' ], |
|
253
|
|
|
[ /this\.base64ToBinary/g, 'base64_decode' ], |
|
254
|
|
|
[ /\.safeFloat/g, '.safe_float'], |
|
255
|
|
|
[ /\.parseOHLCVs/g, '.parse_ohlcvs'], |
|
256
|
|
|
[ /\.parseOHLCV/g, '.parse_ohlcv'], |
|
257
|
|
|
[ /\.parseTicker/g, '.parse_ticker'], |
|
258
|
|
|
[ /\.parseTradesData/g, '.parse_trades_data'], |
|
259
|
|
|
[ /\.parseTrades/g, '.parse_trades'], |
|
260
|
|
|
[ /\.parseTrade/g, '.parse_trade'], |
|
261
|
|
|
[ /\.parseOrderBook/g, '.parse_order_book'], |
|
262
|
|
|
[ /\.parseBidAsks/g, '.parse_bidasks'], |
|
263
|
|
|
[ /\.parseBidAsk/g, '.parse_bidask'], |
|
264
|
|
|
[ /\.binaryConcat/g, '.binary_concat'], |
|
265
|
|
|
[ /\.binaryToString/g, '.binary_to_string' ], |
|
266
|
|
|
[ /\.implodeParams/g, '.implode_params'], |
|
267
|
|
|
[ /\.extractParams/g, '.extract_params'], |
|
268
|
|
|
[ /\.indexBy/g, '.index_by'], |
|
269
|
|
|
[ /\.sortBy/g, '.sort_by'], |
|
270
|
|
|
[ /\.marketIds/g, '.market_ids'], |
|
271
|
|
|
[ /\.marketId/g, '.market_id'], |
|
272
|
|
|
[ /\.fetchOrderStatus/g, '.fetch_order_status'], |
|
273
|
|
|
[ /\.fetchOpenOrders/g, '.fetch_open_orders'], |
|
274
|
|
|
[ /\.fetchOrders/g, '.fetch_orders'], |
|
275
|
|
|
[ /\.parseOrders/g, '.parse_orders'], |
|
276
|
|
|
[ /\.parseOrder/g, '.parse_order'], |
|
277
|
|
|
[ /\.loadMarkets/g, '.load_markets'], |
|
278
|
|
|
[ /\.encodeURIComponent/g, '.encode_uri_component'], |
|
279
|
|
|
[ /this\./g, '$this->' ], |
|
280
|
|
|
[ / this;/g, ' $this;' ], |
|
281
|
|
|
[ /([^'])this_\./g, '$1$this_->' ], |
|
282
|
|
|
[ /\{\}/g, 'array ()' ], |
|
283
|
|
|
[ /\[\]/g, 'array ()' ], |
|
284
|
|
|
[ /\{([^\n\}]+)\}/g, 'array ($1)' ], |
|
285
|
|
|
[ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1list ($2)' ], |
|
286
|
|
|
[ /([^a-zA-Z0-9_])let\s/g, '$1' ], |
|
287
|
|
|
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ], |
|
288
|
|
|
[ /Object\.keys\s*\((.*)\)/g, 'array_keys ($1)' ], |
|
289
|
|
|
[ /([^\s]+\s*\(\))\.toString \(\)/g, '(string) $1' ], |
|
290
|
|
|
[ /([^\s]+)\.toString \(\)/g, '(string) $1' ], |
|
291
|
|
|
[ /throw new Error \((.*)\)/g, 'throw new \\Exception ($1)'], |
|
292
|
|
|
[ /throw new ([\S]+) \((.*)\)/g, 'throw new $1 ($2)'], |
|
293
|
|
|
[ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(\<=|\>=|<|>)\s*(.*)\.length\s*\;([^\)]+)\)\s*{/g, 'for ($1 = $2; $1 $3 count ($4);$5) {'], |
|
294
|
|
|
[ /([^\s]+)\.length\;/g, 'count ($1);' ], |
|
295
|
|
|
[ /([^\s]+)\.length/g, 'strlen ($1)' ], |
|
296
|
|
|
[ /\.push\s*\(([\s\S]+?)\)\;/g, '[] = $1;' ], |
|
297
|
|
|
[ /(\s)await(\s)/g, '$1' ], |
|
298
|
|
|
[ /([\S])\: /g, '$1 => ' ], |
|
299
|
|
|
[ /\{([^\;\{]+?)\}([^\s])/g, 'array ($1)$2' ], |
|
300
|
|
|
[ /\[\s*([^\]]+?)\s*\]\.join\s*\(\s*([^\)]+?)\s*\)/g, "implode ($2, array ($1))" ], |
|
301
|
|
|
[ /\[\s([^\]]+?)\s\]/g, 'array ($1)' ], |
|
302
|
|
|
[ /JSON\.stringify/g, 'json_encode' ], |
|
303
|
|
|
// [ /\'([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "sprintf ('$1', $2)" ], |
|
304
|
|
|
[ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "sprintf ('%$2f', $1)" ], |
|
305
|
|
|
[ /parseFloat\s/g, 'floatval '], |
|
306
|
|
|
[ /parseInt\s/g, 'intval '], |
|
307
|
|
|
[ / \+ /g, ' . ' ], |
|
308
|
|
|
[ / \+\= /g, ' .= ' ], |
|
309
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.toUpperCase\s*\(\)/g, 'strtoupper ($1)' ], |
|
310
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.toLowerCase\s*\(\)/g, 'strtolower ($1)' ], |
|
311
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.replace\s*\(([^\)]+)\)/g, 'str_replace ($2, $1)' ], |
|
312
|
|
|
[ /this\[([^\]+]+)\]/g, '$$this->$$$1' ], |
|
313
|
|
|
[ /([^\s]+).slice \(([^\)\:]+)\)/g, 'mb_substr ($1, $2)' ], |
|
314
|
|
|
[ /([^\s]+).slice \(([^\,\)]+)\,\s*([^\)]+)\)/g, 'mb_substr ($1, $2, $3)' ], |
|
315
|
|
|
[ /([^\s]+).split \(([^\,]+?)\)/g, 'explode ($2, $1)' ], |
|
316
|
|
|
[ /Math\.floor\s*\(([^\)]+)\)/g, '(int) floor ($1)' ], |
|
317
|
|
|
[ /Math\.abs\s*\(([^\)]+)\)/g, 'abs ($1)' ], |
|
318
|
|
|
[ /Math\.round\s*\(([^\)]+)\)/g, '(int) round ($1)' ], |
|
319
|
|
|
[ /([^\(\s]+)\s+%\s+([^\s\)]+)/g, 'fmod ($1, $2)' ], |
|
320
|
|
|
[ /\(([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0\)/g, '(mb_strpos ($1, $2) !== false)' ], |
|
321
|
|
|
[ /([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0/g, 'mb_strpos ($1, $2) !== false' ], |
|
322
|
|
|
[ /([^\s]+)\.indexOf\s*\(([^\)]+)\)/g, 'mb_strpos ($1, $2)' ], |
|
323
|
|
|
[ /\(([^\s]+)\sin\s([^\)]+)\)/g, '(array_key_exists ($1, $2))' ], |
|
324
|
|
|
[ /([^\s]+)\.join\s*\(\s*([^\)]+?)\s*\)/g, 'implode ($2, $1)' ], |
|
325
|
|
|
[ /Math\.(max|min)/g, '$1' ], |
|
326
|
|
|
[ /console\.log/g, 'var_dump'], |
|
327
|
|
|
[ /process\.exit/g, 'exit'], |
|
328
|
|
|
] |
|
329
|
|
|
|
|
330
|
|
|
let pyRegexSync = pyRegex.concat ([ |
|
331
|
|
|
[ /(\s)await(\s)/g, '$1' ] |
|
332
|
|
|
]) |
|
333
|
|
|
|
|
334
|
|
|
let pyBody = regexAll (body, pyRegexSync) |
|
335
|
|
|
let pyBodyAsync = regexAll (body, pyRegex) |
|
336
|
|
|
|
|
337
|
|
|
// special case for Python OrderedDicts |
|
338
|
|
|
|
|
339
|
|
|
let orderedRegex = /\.ordered\s+\(\{([^\}]+)\}\)/g |
|
340
|
|
|
let orderedMatches = undefined |
|
|
|
|
|
|
341
|
|
|
while (orderedMatches = orderedRegex.exec (pyBody)) { |
|
342
|
|
|
let replaced = orderedMatches[1].replace (/^(\s+)([^\:]+)\:\s*([^\,]+)\,$/gm, '$1($2, $3),') |
|
343
|
|
|
pyBody = pyBody.replace (orderedRegex, '\.ordered ([' + replaced + '])') |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
let pyString = 'def ' + method + '(self' + (pyArgs.length ? ', ' + pyArgs.replace (/undefined/g, 'None').replace (/false/g, 'False').replace (/true/g, 'True') : '') + '):' |
|
347
|
|
|
|
|
348
|
|
|
py.push (''); |
|
349
|
|
|
py.push (' ' + pyString); |
|
350
|
|
|
py.push (pyBody); |
|
351
|
|
|
|
|
352
|
|
|
pyAsync.push (''); |
|
353
|
|
|
pyAsync.push (' ' + keyword + pyString); |
|
354
|
|
|
pyAsync.push (pyBodyAsync); |
|
355
|
|
|
|
|
356
|
|
|
let phBody = regexAll (body, phRegex.concat (phVarsRegex)) |
|
357
|
|
|
|
|
358
|
|
|
ph.push (''); |
|
359
|
|
|
ph.push (' public function ' + method + ' (' + phArgs.replace (/undefined/g, 'null').replace ('{}', 'array ()') + ') {'); |
|
360
|
|
|
ph.push (phBody); |
|
361
|
|
|
ph.push (' }') |
|
362
|
|
|
} |
|
363
|
|
|
|
|
364
|
|
|
py.push ('') |
|
365
|
|
|
pyAsync.push ('') |
|
366
|
|
|
|
|
367
|
|
|
python.push (py.join ("\n")) |
|
368
|
|
|
pythonAsync.push (pyAsync.join ("\n")) |
|
369
|
|
|
|
|
370
|
|
|
ph.push ('}') |
|
371
|
|
|
ph.push ('') |
|
372
|
|
|
|
|
373
|
|
|
php.push (ph.join ("\n")) |
|
374
|
|
|
} |
|
375
|
|
|
|
|
376
|
|
|
//----------------------------------------------------------------------------- |
|
377
|
|
|
|
|
378
|
|
|
function transpile (oldName, newName, content, comment = '//') { |
|
379
|
|
|
log.bright.cyan ('Transpiling ' + oldName.yellow + ' → ' + newName.yellow) |
|
380
|
|
|
let fileContents = fs.readFileSync (oldName, 'utf8') |
|
381
|
|
|
fileContents = fileContents.split ("\n" + comment + "====") [0] |
|
382
|
|
|
fileContents += |
|
383
|
|
|
"\n" + comment + "==============================================================================\n" + |
|
384
|
|
|
content.join ("\n" + comment + "------------------------------------------------------------------------------\n") |
|
385
|
|
|
fs.truncateSync (newName) |
|
386
|
|
|
fs.writeFileSync (newName, fileContents) |
|
387
|
|
|
} |
|
388
|
|
|
|
|
389
|
|
|
//----------------------------------------------------------------------------- |
|
390
|
|
|
|
|
391
|
|
|
function copyFile (oldName, newName) { |
|
392
|
|
|
let contents = fs.readFileSync (oldName, 'utf8') |
|
393
|
|
|
fs.truncateSync (newName) |
|
394
|
|
|
fs.writeFileSync (newName, contents) |
|
395
|
|
|
} |
|
396
|
|
|
|
|
397
|
|
|
//----------------------------------------------------------------------------- |
|
398
|
|
|
|
|
399
|
|
|
transpile ('./ccxt/exchanges.py', './ccxt/exchanges.py', python, '#') |
|
400
|
|
|
transpile ('./ccxt/async/exchanges.py', './ccxt/async/exchanges.py', pythonAsync, '#') |
|
401
|
|
|
transpile ('./ccxt.php', './build/ccxt.php', php, '//') |
|
402
|
|
|
|
|
403
|
|
|
//----------------------------------------------------------------------------- |
|
404
|
|
|
|
|
405
|
|
|
log.bright.green ('Transpiled successfully.') |
|
406
|
|
|
|